﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using huqiang;
public class FilePacker
{
    public static int Pack(string savePath, string readFolder, string[] files)
    {
        byte[] buffer = new byte[1024 * 1024 * 2];
        if (File.Exists(savePath))
            File.Delete(savePath);
        FileStream fs = File.Create(savePath);
        //int sub = readFolder.Length;
        for (int i = 0; i < files.Length; i++)
        {
            string path = files[i];
            if (readFolder != null & readFolder != "")
                path = readFolder + "/" + path;
            if (File.Exists(path))
            {
                string file = files[i];
                byte[] dat = Encoding.UTF8.GetBytes(file);
                fs.Write(dat.Length.ToBytes(), 0, 4);
                fs.Write(dat, 0, dat.Length);

                FileStream input = File.OpenRead(path);
                int len = (int)input.Length;
                fs.Write(len.ToBytes(), 0, 4);
                int r = 0;
                while ((r = input.Read(buffer, 0, buffer.Length)) > 0)
                {
                    fs.Write(buffer, 0, r);
                }
                input.Dispose();
            }
        }
        int l = (int)fs.Length;
        fs.Flush();
        fs.Dispose();
        return l;
    }
    public static void Append(string savepath,string file, string name)
    {
        byte[] buffer = new byte[1024 * 1024 * 2];
        FileStream fs = File.Open(savepath,FileMode.OpenOrCreate);
        //int sub = readFolder.Length;
        if (File.Exists(file))
        {
            fs.Seek(fs.Length,SeekOrigin.Begin);
            byte[] dat = Encoding.UTF8.GetBytes(name);
            fs.Write(dat.Length.ToBytes(), 0, 4);
            fs.Write(dat, 0, dat.Length);

            FileStream input = File.OpenRead(file);
            int len = (int)input.Length;
            fs.Write(len.ToBytes(), 0, 4);
            int r = 0;
            while ((r = input.Read(buffer, 0, buffer.Length)) > 0)
            {
                fs.Write(buffer, 0, r);
            }
            input.Dispose();
        }
        fs.Flush();
        fs.Dispose();
    }

    public static int Pack(string savePath,string readFolder, List<string> files)
    {
        byte[] buffer = new byte[1024 * 1024 * 2];
        if (File.Exists(savePath))
            File.Delete(savePath);
        FileStream fs = File.Create(savePath);
        //int sub = readFolder.Length;
        for (int i = 0; i < files.Count; i++)
        {
            string path = files[i];
            if (readFolder != null & readFolder != "")
                path = readFolder + "/" + path;
            if(File.Exists(path))
            {
                string file = files[i];
                byte[] dat = Encoding.UTF8.GetBytes(file);
                fs.Write(dat.Length.ToBytes(), 0, 4);
                fs.Write(dat, 0, dat.Length);

                FileStream input = File.OpenRead(path);
                int len = (int)input.Length;
                fs.Write(len.ToBytes(), 0, 4);
                int r = 0;
                while ((r = input.Read(buffer, 0, buffer.Length)) > 0)
                {
                    fs.Write(buffer, 0, r);
                }
                input.Dispose();
            }
        }
        int l =(int) fs.Length;
        fs.Flush();
        fs.Dispose();
        return l;
    }
    public static void CheckOrCreateFolder(string Folder, string exFolder, bool isFile = false)
    {
        if(Directory.Exists(Folder))
        {
            string[] ss = exFolder.Split('/');
            string path = Folder;
            int len = ss.Length;
            if (isFile)
                len--;
            for (int i = 0; i < len; i++)
            {
                path = path + "/" + ss[i];
                if (!Directory.Exists(path))
                    Directory.CreateDirectory(path);
            }
        }
    }
    public int AllLength;
    public int curLength;
    public string Tag;
    public void UnPack(string file, string folder)
    {
        if(File.Exists(file))
        {
            int bl = 1024 * 1024 * 2;
            byte[] buffer = new byte[bl];
            FileStream fs = File.Open(file, FileMode.Open);
            int len = (int)fs.Length;
            AllLength = len;
            curLength = 0;
            int s = 0;
            while (s < len)
            {
                fs.Read(buffer, 0, 4);
                int fl = buffer.ReadInt32(0);
                fs.Read(buffer,0,fl);
                string name = Encoding.UTF8.GetString(buffer,0,fl);
                fs.Read(buffer, 0, 4);
                fl = buffer.ReadInt32(0);
                if(fl>0)
                {
                    CheckOrCreateFolder(folder, name, true);
                    string path = folder + "/" + name;
                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                    FileStream output = File.Create(path);
                    try
                    {
                        int p = fl / bl;
                        int r = fl % bl;
                        for (int i = 0; i < p; i++)
                        {
                            fs.Read(buffer, 0, bl);
                            output.Write(buffer, 0, bl);
                        }
                        if (r > 0)
                        {
                            fs.Read(buffer, 0, r);
                            output.Write(buffer, 0, r);
                        }
                        output.Flush();
                        output.Dispose();
                    }
                    catch
                    {
                        output.Flush();
                        output.Dispose();
                        fs.Dispose();
                        UnityEngine.Debug.LogError("解压失败!");
                        throw new Exception();
                    }
                }
                s = (int) fs.Position;
                curLength = s;
            }
            fs.Dispose();
        }
    }
    public async void UnpackAsync(string file, string folder,Action compelete)
    {
        await Task.Run(()=> {
            UnPack(file, folder);
        });
        if (compelete != null)
            compelete();
    }
}
